package com.hoki.zj.hrm.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.hoki.zj.hrm.asserts.GlobalAssert;
import com.hoki.zj.hrm.domain.CourseType;
import com.hoki.zj.hrm.mapper.CourseTypeMapper;
import com.hoki.zj.hrm.service.ICourseTypeService;
import com.hoki.zj.hrm.vo.CourseTypeVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author shukei
 * @since 2021-09-14
 */
@Service
@CacheConfig(cacheNames = "course-type")
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {

    @Autowired
    private CourseTypeMapper courseTypeMapper;

//    /** 注入自定义的RedisTemplate<Object, Object> */
//    @Autowired
//    private RedisTemplate<Object, Object> redisTemplate;

//    private static final String allCourseTypesKey = "ALL_COURSE_TYPE";

    /**
     * 1.树状菜单（课程类型）查询
     * 后台管理页面/前台首页 :树状列表
     * @return 返回课程类型的集合
     */
    @Override
    @Cacheable(key = "'ALL'")
    public List<CourseType> getTreeDataOfCourseType() {
        // 1.查询数据转换为树状,返回
        return courseTypeToTreeData(baseMapper.selectList(null));
    }

    /**
     * 树状菜单（课程类型）转换
     */
    private List<CourseType> courseTypeToTreeData(List<CourseType> allCourseTypes) {
        // 1.循环查询所有一级课程类型
        List<CourseType> rootCourse = new ArrayList<>();

        Map<Long, CourseType> collect = allCourseTypes.stream().
                collect(Collectors.toMap(CourseType :: getId, allCourseType -> allCourseType));

        allCourseTypes.forEach(courseType -> {
            if (courseType.getPid() == null || courseType.getPid() == 0) {
                // 如果没有pid,就加入到一级课程中
                rootCourse.add(courseType);
            } else {
                // 如果有pid的则分别加入到pid对应的上级课程类型的children List集合中
                /*for (CourseType parentCourseType : allCourseTypes) {
                    if (courseType.getPid().equals(parentCourseType.getId())) {
                        parentCourseType.getChildren().add(courseType);
                        break; // 添加后结束当前循环
                    }
                }*/
                collect.get(courseType.getPid()).getChildren().add(courseType);
            }
        });
        // 所有一级课程类型,和其中的children都已经查询完毕,返回即可
        return rootCourse;
    }

    /**
     * 3.添加: 清除缓存 キャッシュクリア
     */
    @Override
    @CacheEvict(key = "'ALL'")
    public boolean insert(CourseType entity) {
        return super.insert(entity);
    }

    /**
     * 4.修改: 清除缓存 キャッシュクリア
     */
    @Override
    @CacheEvict(key = "'ALL'")
    public boolean updateById(CourseType entity) {
        return super.updateById(entity);
    }

    /**
     * 5.删除: 清除缓存 キャッシュクリア
     */
    @Override
    @CacheEvict(key = "'ALL'")
    public boolean deleteById(Serializable id) {
        return super.deleteById(id);
    }

    /**
     * 前台列表展示页 list
     * @param id コースid
     * @return List<CourseType>
     *
     * courseTypeVo: {
     *     ownerCourseType: {},
     *     otherCourseTypes:{}
     * }
     */
    @Override
    public List<CourseTypeVO> getCrumbsDataOfCourseType(Long id) {
        // 1.判断id是否非法
        GlobalAssert.isNull(id, "id不能为空!");
        // 2.构造一个课程类型VO对象结果集合
        List<CourseTypeVO> courseTypeVOs = new ArrayList<>();
        // 3.根据id查出当前id对应的课程类型
        CourseType courseType = baseMapper.selectById(id);
        // 4.判断课程类型是否存在
        GlobalAssert.isNull(courseType, "课程类型不存在!");
        // 5.获取当前课程类型的path(包含自己在内的所有父类)
        String[] paths = courseType.getPath().split("\\."); // 获取当前课程的path(即所有父类型)
        // 6.批量查询出所有课程类型(自己和父类的)
        List<CourseType> courseTypes = baseMapper.selectBatchIds(Arrays.asList(paths));
        // 7.循环遍历
        courseTypes.forEach(currentTypes -> { // 每次遍历到的课程类型
            // 构造一个CourseTypeVO视图对象
            CourseTypeVO courseTypeVO = new CourseTypeVO();
            // 设置ownerCourseType
            courseTypeVO.setOwnerCourseType(currentTypes);
            // 查询当前循环课程类型对象的所有同级类型,根据pid
            Long pid = currentTypes.getPid();
            Wrapper<CourseType> wrapper = new EntityWrapper<>();
            wrapper.eq("pid", pid);
            List<CourseType> otherCourseTypes = baseMapper.selectList(wrapper);
            // 设置otherCourseTypes
            courseTypeVO.setOtherCourseTypes(otherCourseTypes);
            // 设置课程类型VO对象结果集
            courseTypeVOs.add(courseTypeVO);
        });
        return courseTypeVOs;
    }
}
